package io.adrainty.bolee.insurance.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator;
import io.adrainty.bolee.framework.commons.basic.BaseBO;
import io.adrainty.bolee.insurance.models.entity.InsurancePlanEntity;
import io.adrainty.bolee.insurance.models.entity.PlanEarningsEntity;
import io.adrainty.bolee.insurance.models.entity.PlanSafeguardEntity;
import io.adrainty.bolee.insurance.repository.IInsuranceRepository;
import io.adrainty.bolee.insurance.service.IInsurancePlanService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>InsurancePlanServiceImpl</p>
 *
 * @author AdRainty
 * @version V1.0.0
 * @description IInsurancePlanService
 * @since 2025/8/14 14:06:40
 */

@Service
public class InsurancePlanServiceImpl implements IInsurancePlanService {

    @Resource
    private IInsuranceRepository insuranceRepository;

    @Resource
    private IdentifierGenerator identifierGenerator;

    @Override
    @Transactional
    public Boolean createInsurancePlans(List<InsurancePlanEntity> insurancePlanVOs) {
        insurancePlanVOs.forEach(entity -> entity.setPlanNo(identifierGenerator.nextId(entity).longValue()));
        insuranceRepository.createInsurancePlans(insurancePlanVOs);

        // 构建方案保障项List对象
        List<PlanSafeguardEntity> planSafeguardEntities = new ArrayList<>();
        // 构建方案给付计划List对象
        List<PlanEarningsEntity> planEarningsEntities = new ArrayList<>(insurancePlanVOs.size());

        for (InsurancePlanEntity ipv : insurancePlanVOs) {
            PlanEarningsEntity earningsVO = ipv.getPlanEarningsVO();
            List<PlanSafeguardEntity> safeguardVOs = ipv.getPlanSafeguardVOs();

            if (earningsVO != null) {
                earningsVO.setPlanId(ipv.getId());
                planEarningsEntities.add(earningsVO);
            }

            if (CollUtil.isNotEmpty(safeguardVOs)) {
                safeguardVOs.forEach(s -> s.setPlanId(ipv.getId()));
                planSafeguardEntities.addAll(safeguardVOs);
            }
        }

        insuranceRepository.saveBatchPlanEarnings(planEarningsEntities);
        insuranceRepository.saveBatchPlanSafeguard(planSafeguardEntities);
        return Boolean.TRUE;
    }

    @Override
    @Transactional
    public Boolean updateInsurancePlans(List<InsurancePlanEntity> insurancePlanVOs) {
        if (CollUtil.isEmpty(insurancePlanVOs)) return Boolean.TRUE;
        InsurancePlanEntity first = insurancePlanVOs.get(0);
        Long insuranceId = first.getInsuranceId();
        List<InsurancePlanEntity> planList = insuranceRepository.getPlansByInsuranceId(insuranceId);

        List<Long> planIds = planList.stream().map(InsurancePlanEntity::getId).toList();
        removeInsurancePlanExtra(planIds);

        insurancePlanVOs.forEach(item -> item.setBaseEntity(BaseBO.DEFAULT_));
        return this.createInsurancePlans(insurancePlanVOs);
    }

    @Override
    public List<InsurancePlanEntity> findPlanList(InsurancePlanEntity planDTO) {
        List<InsurancePlanEntity> planList = insuranceRepository.findPlanList(planDTO);
        fillPlanData(planList);
        return planList;
    }

    /**
     * 删除保险计划关联数据
     * @param planIds 保险计划id
     */
    private void removeInsurancePlanExtra(List<Long> planIds) {
        insuranceRepository.deletePlanByPlanId(planIds);
        insuranceRepository.deletePlanSafeguardByPlanId(planIds);
        insuranceRepository.deletePlanEarningsByPlanId(planIds);
    }

    /**
     * 填充保险计划数据
     * @param planList 保险计划列表
     */
    private void fillPlanData(List<InsurancePlanEntity> planList) {
        if (CollUtil.isEmpty(planList)) return;
        List<Long> planIds = planList.stream().map(InsurancePlanEntity::getId).toList();
        Map<Long, List<PlanSafeguardEntity>> safeguardMap = insuranceRepository.findPlanSafeguardByPlanId(planIds).stream()
                .collect(Collectors.groupingBy(PlanSafeguardEntity::getPlanId));
        Map<Long, PlanEarningsEntity> earningsMap = insuranceRepository.findPlanEarningsByPlanId(planIds).stream()
                .collect(Collectors.toMap(PlanEarningsEntity::getPlanId, earnings -> earnings));
        for (InsurancePlanEntity planEntity : planList) {
            planEntity.setPlanSafeguardVOs(safeguardMap.getOrDefault(planEntity.getId(), new ArrayList<>()));
            planEntity.setPlanEarningsVO(earningsMap.get(planEntity.getId()));
        }
    }

}
